// Copyright (c) 2019 Presto Labs Pte. Ltd.
// Author: linchuan, gekim

#pragma once

#include <memory>
#include <string>

#include "coin2/base/string_util.h"
#include "coin2/exchange/base/symbology/currency.h"
#include "coin2/exchange/base/symbology/util.h"

namespace coin2::exchange::bitmex::symbology {

static const int64_t LUNA2_LIST_TIME = 1653955200000000000L; // TimestampFromDatetime(2020, 05, 31);

class BitmexCurrency : public base::symbology::Currency,
                       public base::symbology::CurrencyFromStrMixin<BitmexCurrency> {
 public:
  using ExchangeType = base::market::ExchangeType;
  using MarketType = base::market::MarketType;
  using Currency = base::symbology::Currency;
  using base::symbology::Currency::native_currency;

 public:
  explicit BitmexCurrency(const std::string& currency)
      : Currency(currency, ToNativeCurrencyFutures(currency).value(), ExchangeType::Bitmex) {}

  static std::unique_ptr<BitmexCurrency> FromNativeStrImpl(
      const std::string& native_currency_str,
      int64_t resolve_timestamp) {
    auto currency = FromNativeCurrencyFutures(native_currency_str, resolve_timestamp);
    if (currency) {
      return std::make_unique<BitmexCurrency>(currency.value());
    }
    return {};
  }

  static std::unique_ptr<BitmexCurrency> FromNormStrImpl(
      const std::string& currency_str,
      int64_t resolve_timestamp) {
    auto native_currency = ToNativeCurrencyFutures(currency_str);
    if (!native_currency) {
      return {};
    }
    auto norm_currency = FromNativeCurrencyFutures(*native_currency, resolve_timestamp);
    if (!norm_currency) {
      return {};
    }
    return std::make_unique<BitmexCurrency>(norm_currency.value());
  }

 private:
  static std::optional<std::string> ToNativeCurrencyFutures(const std::string& currency_str) {
    using base::symbology::HasValue;

    // if (!kBitmexProductInfo.HasNormCurrency(currency_str)) {
    //   return {};
    // }

    std::string native_currency_str;
    if (currency_str == "BTC") {
      native_currency_str = "XBT";
    } else if (currency_str == "BCHABC" || currency_str == "BCHN") {
      native_currency_str = "BCH";
    } else if (currency_str == "LUNA2"){
      return "LUNA";
    } else {
      native_currency_str = currency_str;
    }
    return native_currency_str;
  }

  static std::optional<std::string> FromNativeCurrencyFutures(
      const std::string& native_currency_str,
      int64_t resolve_timestamp) {
    using base::symbology::HasValue;

    std::string remove_digit_currency = native_currency_str;
    remove_digit_currency.erase(std::remove_if(remove_digit_currency.begin(), remove_digit_currency.end(), ::isdigit), remove_digit_currency.end());
    if (!StringIsUpper(remove_digit_currency)) {
      return {};
    }

    // if (!kBitmexProductInfo.HasNativeCurrency(native_currency_str)) {
    //   return {};
    // }

    std::string currency_str;
    if (native_currency_str == "XBT") {
      currency_str = "BTC";
    } else if (native_currency_str == "BCH") {
      if (resolve_timestamp >= base::symbology::BCHA_BCHN_FORK_TIME) {
        currency_str = "BCHN";
      } else {
        currency_str = "BCHABC";
      }
    } else if (native_currency_str == "LUNA" && resolve_timestamp >= LUNA2_LIST_TIME){
      return "LUNA2";
    } else {
      currency_str = native_currency_str;
    }

    return currency_str;
  }
};

}  // namespace coin2::exchange::bitmex::symbology
